package org.tio.showcase.dbUtil;

import com.alibaba.fastjson.JSON;
import com.mongodb.*;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.tio.showcase.http.model.User;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import static com.mongodb.client.model.Filters.eq;

/**
 *      <!--MongoDB 连接依赖-->
 * 		<dependency>
 * 			<groupId>org.mongodb</groupId>
 * 			<artifactId>mongo-java-driver</artifactId>
 * 		</dependency>
 */
public class MongodbUtil {

    public static final String IP = "localhost";
    public static final int PROT = 27017;

    // 获取连接
    public static MongoDatabase getAuthConnect(String databaseName){
        // 连接到 mongodb 服务
        MongoClient mongoClient = new MongoClient(IP, PROT);
        // 连接到数据库
        MongoDatabase mongoDatabase = mongoClient.getDatabase(databaseName);
        System.out.println("Connect to database successfully");
        return mongoDatabase;
    }

    // 三个参数分别为 用户名  密码  数据库名称
    public static MongoDatabase getAuthConnect(String username,String password,String databaseName){
        ServerAddress serverAddress = new ServerAddress(IP,PROT);
        List<ServerAddress> addrs = new ArrayList<ServerAddress>();
        addrs.add(serverAddress);

        //MongoCredential.createScramSha1Credential()三个参数分别为 用户名 数据库名称 密码
        MongoCredential credential = MongoCredential.createScramSha1Credential(username, databaseName, password.toCharArray());
        List<MongoCredential> credentials = new ArrayList<MongoCredential>();
        credentials.add(credential);

        //通过连接认证获取MongoDB连接
        MongoClient mongoClient = new MongoClient(addrs,credentials);

        //连接到数据库
        MongoDatabase mongoDatabase = mongoClient.getDatabase(databaseName);
        return mongoDatabase;
    }
    public static MongoDatabase getAuthConnect(){
        return getAuthConnect("test");
    }

    // 创建数据集合（类似mysql 的数据表）
    public static void createDataBase(){
        getAuthConnect().createCollection("test2");
        System.out.println("集合创建成功");
    }

    // 获取集合
    public static MongoCollection<Document> getCollection(String c){
        // 获取集合，获取
        MongoCollection<Document> collection = getAuthConnect().getCollection(c);
        System.out.println("集合获取成功");
        return collection;
    }
    public static MongoCollection<Document> getCollection(){
        return getCollection("collection2");
    }

    /**
     * 插入文档
     * 1. 创建文档 org.bson.Document 参数为key-value的格式
     * 2. 创建文档集合List<Document>
     * 3. 将文档集合插入数据库集合中 mongoCollection.insertMany(List<Document>) 插入单个文档可以用 mongoCollection.insertOne(Document)
     * */
    public static void addDataBase(){
            // 写法 1
             Document document = new Document("title", "MongoDB").
                     append("description", "database").
                     append("likes", 100).
                     append("by", "Fly");

            // 写法 2
            // Document document = new Document();
            //=================================//
            document.put("age","123");
            List<Document> documents = new ArrayList<Document>();
            documents.add(document);
            getCollection().insertMany(documents);
            System.out.println("文档插入成功");
    }

    public static void addDataBase(Map map){
        Document document = new Document(map);
        List<Document> list = new ArrayList<Document>();
        list.add(document);
        getCollection().insertMany(list);
    }

    // 更新文档   将文档中likes=100的文档修改为likes=200
    public static void updataDataBase(){
        getCollection().updateMany(eq("age", "123"),
                new Document("$set",new Document("age","22")));
    }

    /**
     * 检索所有文档（类似 mysql 查询所有）
     *
     */
    public static void getAll(){
        // 获取所有,使用遍历器遍历结果
        // 1. 获取迭代器FindIterable<Document>
        // 2. 获取游标MongoCursor<Document>
        // 3. 通过游标遍历检索出的文档集合
        FindIterable<Document> findIterable = getCollection().find();
        MongoCursor<Document> mongoCursor = findIterable.iterator();
        while(mongoCursor.hasNext()){
            System.out.println(mongoCursor.next().toJson());

        }

        DBObject query = new BasicDBObject();
        query.put("id",999);
        // 对所有结果使用阻塞回调方法
        getCollection().find().skip(5).limit(5).forEach((Block<Document>) document -> {
            // 获取指定 key 的值
            String title = document.getString("title");
//            List<String> tags = (List<String>) document.get("age");
            System.out.println(document.toJson());
//            String s = JSON.toJSONString(document.toJson());
//            JSONObject jsonObject = JSONObject.parseObject(s);
//            jsonObject.remove("_id");
//            //User u = (User) JSON.parseArray(s,User.class);
//            System.out.println(jsonObject);
        });

        // 模糊查询匹配
        BasicDBObject cond=new BasicDBObject();
        Pattern pattern=Pattern.compile("^.*"+"ngo"+".*$");
        cond.put("title", pattern);
        cond.put("description",Pattern.compile("^.*"+"sql"+".*$"));
        getCollection().find(cond).forEach((Block<Document>) document ->{
            System.out.println(document);
        });

    }


    public static void delete(){
        //删除第一条满足查询条件的文档记录，对应 delete(<query>,{justOne:true}) 方法
        //getCollection().deleteOne(eq("nick",null));

        //删除所有满足查询条件的文档记录，对应 delete(<query>,{justOne:false}) 方法
        //getCollection().deleteMany(gte("nick",null));
    }


    public static void findDocumentById(String id) {
        BasicDBObject query = new BasicDBObject();
        query.put("_id", new ObjectId(id));
        getCollection().find(query).forEach((Block<Document>) document ->{
            String str = document.toString().replace("Document{{_id="+id+",","{");
            str = str.replace("}}","}"); // str.substring(0,str.length()-1);
            System.out.println(str);
           User user = JSON.toJavaObject(JSON.parseObject(str), User.class);
            System.out.println(user);
        });
    }


    /**
     * 将Object对象里面的属性和值转化成Map对象
     *
     * @param obj
     * @return
     * @throws IllegalAccessException
     */
    public static Map<String, Object> objectToMap(Object obj) throws IllegalAccessException {
        Map<String, Object> map = new HashMap<String,Object>();
        Class<?> clazz = obj.getClass();
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            String fieldName = field.getName();
            Object value = field.get(obj);
            map.put(fieldName, value);
        }
        return map;
    }
    public static void main(String args[]) {
        try {


//            for (int i = 0; i < 10; i++) {
//                int c = (int) (Math.random() * 100);
//                User user = new User();
//                user.setId(c);
//                user.setIp("127.0.0.1");
//                user.setLoginname("你好朋友");
//                user.setNick("备注开心");
//                addDataBase(objectToMap(user));
//            }
//             delete();
            //getAll();
            findDocumentById("5ddb739115d4cf4c0e9a0a38");

        } catch (Exception e) {
            System.err.println(e.getClass().getName() + ": " + e.getMessage());
        }
    }
}